package cn.edu.cug.cs.gtl.gsm.memory;

import cn.edu.cug.cs.gtl.common.Identifier;
import cn.edu.cug.cs.gtl.gsm.PaginationStorageManager;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
/**
 * 实现多内存块分页读写
 */
public class MemoryStorageManager extends PaginationStorageManager {
    ArrayList<byte[]> memoryBlocks = new ArrayList<>();
    byte [] datBlock;//当前数据内存块

    /**
     * @param collectionSize
     * @param pageSize
     */
    public MemoryStorageManager(long collectionSize, int pageSize) {
        super(collectionSize, pageSize);
        this.datBlock = new byte[pageSize];
        memoryBlocks.add(this.datBlock);
    }

    /**
     * @param baseName
     * @param collectionSize
     * @param pageSize
     */
    public MemoryStorageManager(String baseName, long collectionSize, int pageSize) {
        super(collectionSize, pageSize);
        this.datBlock = new byte[pageSize];
        memoryBlocks.add(this.datBlock);
        this.metaItem.setBaseName(baseName);
    }


    @Override
    protected void readBufferFromPage(Identifier pageIdentifier) throws IOException {
        int order = this.metaItem.getCollectionOrder(pageIdentifier);
        long pos = pageIdentifier.longValue()*getPageSize() - getCollectionSize()*order*getPageSize();
        //需要进行内存块切换
        if(order!=getCurrentCollectionOrder()){
            setCurrentCollectionOrder(order);
            this.datBlock = memoryBlocks.get(order);
        }
        System.arraycopy(this.datBlock,(int) pos,this.pageBuffer,0,getPageSize());
    }

    @Override
    protected void writeBufferToPage(Identifier pageIdentifier) throws IOException {
        int order = this.metaItem.getCollectionOrder(pageIdentifier);
        long pos = pageIdentifier.longValue()*getPageSize() - getCollectionSize()*order*getPageSize();
        //需要进行内存块切换
        if(order!=getCurrentCollectionOrder()){
            setCurrentCollectionOrder(order);
            if(order<memoryBlocks.size())
                this.datBlock = memoryBlocks.get(order);
            else {
                this.datBlock = new byte[getPageSize()*2];
                memoryBlocks.add(this.datBlock);
            }
        }
        //扩展内存的长度
        if(this.datBlock.length<pos+getPageSize()){
            this.datBlock = Arrays.copyOf(this.datBlock,(int)(pos+getPageSize()*2));
        }
        System.arraycopy(this.pageBuffer,0,this.datBlock,(int) pos,getPageSize());
        memoryBlocks.set(order,this.datBlock);
    }

    @Override
    protected void readMetaFromStorage() throws IOException {
        //do nothing
    }

    @Override
    protected void writeMetaToStorage() throws IOException {
        //do nothing
    }

    @Override
    protected void readIndicesFromStorage() throws IOException {
        //do nothing
    }

    @Override
    protected void writeIndicesToStorage() throws IOException {
        //do nothing
    }

    @Override
    protected void closeStorages() throws IOException {
        this.datBlock=null;
        this.memoryBlocks.clear();
        this.memoryBlocks=null;
    }

}
